const cheerio = require("cheerio");
const { setUserAgent } = require("./ua");
const axios = require("axios");

async function fetchHtml(url, method = "get", data) {
	try {
		const response = await axios({
			url,
			method,
			data,
			headers: {
				Accept: "*/*",
				"accept-encoding": null,
				"accept-language": "zh-CN,zh;q=0.9",
				...setUserAgent(),
			},
		});
		return response.data;
	} catch (error) {
		console.error(`Error fetching HTML from ${url}:`, error.message);
		throw new Error(`Error fetching HTML: ${error.message}`);
	}
}

const htmlParseCatalogs = async (url) => {
	let content = await getDeepthHtml(url);

	if (!content) {
		return false;
	}
	const result = handlerCatelogs(content);
	return result;
};

const getDeepthHtml = async (url, content = {}) => {
	try {
		let res = await fetchHtml(url);

		if (res) {
			const $ = cheerio.load(res);

			const bookName = $('meta[property="og:novel:book_name"]').attr(
				"content"
			);
			const author = $('meta[property="og:novel:author"]').attr(
				"content"
			);
			const image = $('meta[property="og:image"]').attr("content");

			if (!content.isParse) {
				const parse = new URL(url);
				content = {
					isParse: true,
					origin: parse.origin,
					pathname: parse.pathname,
					bookName,
					author,
					image,
					isLoaded: [url],
					links: [],
				};
			}

			const tagList = $("a");
			for (let index = 0; index < tagList.length; index++) {
				const element = tagList[index];
				const path = $(element).attr("href");

				if (
					path?.startsWith("https://") ||
					path?.startsWith("http://")
				) {
					continue;
				} else {
					if (
						path?.startsWith(content.pathname) &&
						path?.endsWith(".html")
					) {
						if (!content.links) {
							content.links = [];
						}
						content.links.push({
							href: $(element).attr("href"),
							text: $(element).text(),
						});
					}

					if (
						path?.startsWith(content.pathname) &&
						!path?.endsWith(".html")
					) {
						let nextPath = `${content.origin}${$(element).attr(
							"href"
						)}`;
						let path1, path2;
						if (nextPath.endsWith("/")) {
							path1 = nextPath.slice(0, nextPath.length - 1);
							path2 = nextPath;
						} else {
							path1 = `${nextPath}/`;
							path2 = nextPath;
						}

						if (
							content.isLoaded.includes(path1) ||
							content.isLoaded.includes(path2)
						) {
							continue;
						}

						if (!content.isLoaded.includes(nextPath)) {
							content.isLoaded.push(nextPath);
							content = await getDeepthHtml(nextPath, content);
						}
					}
				}
			}
		}
	} catch (error) {
		return false;
	}

	return content;
};

const handlerCatelogs = (content) => {
	const array = content.links || [];

	// 过滤重复的 href
	const uniqueArray = Array.from(new Set(array.map((item) => item.href))).map(
		(href) => array.find((item) => item.href === href)
	);

	// 按照 xxxx.html 从小到大排序
	uniqueArray.sort((a, b) => {
		const numA = parseInt(a.href.split("/").pop().split(".html")[0]);
		const numB = parseInt(b.href.split("/").pop().split(".html")[0]);
		return numA - numB;
	});

	content.links = uniqueArray;

	const { origin, pathname, bookName, author, links, isLoaded, image } =
		content;

	return { origin, pathname, bookName, author, links, isLoaded, image };
};

const getBookPageContent = async (params) => {
	const content = await getDeepthPage(params);
	if (!content) {
		return false;
	}
	const result = handlerPage(content);
	return result;
};

const getDeepthPage = async (params, content = {}) => {
	try {
		const { origin, href } = params;
		const or = origin.endsWith("/")
			? origin.slice(0, origin.length - 1)
			: origin;
		const url = `${or}${href}`;
		const res = await fetchHtml(url);
		const $ = cheerio.load(res);

		if (!content.isParse) {
			content = {
				isParse: true,
				text: "",
				isLoaded: [href],
			};
		}

		$("p").each((index, element) => {
			let parent = $(element)?.parent();
			let grandParent = parent?.parent();

			if (parent?.is(".footer") || grandParent?.is(".footer")) {
				return;
			}

			const text = $(element).text();
			content.text += `${text}`;
		});

		if (!$("p").length) {
			content.text = $(".showtxt").text();
		}

		const commonLink = href.split(".")[0];
		const targetLinks = $(`a[href^="${commonLink}"]`);

		for (let i = 0; i < targetLinks.length; i++) {
			const element = targetLinks[i];
			const nextHref = $(element).attr("href");

			if (!content.isLoaded.includes(nextHref)) {
				content.isLoaded.push(nextHref);
				content = await getDeepthPage(
					{
						origin,
						href: nextHref,
					},
					content
				);
			}
		}
	} catch (error) {
		return false;
	}

	return content;
};

const handlerPage = (content) => {
	let { text } = content;

	text = text.replace(/\n\n/g, "\n");

	return { text };
};

module.exports = {
	fetchHtml,
	htmlParseCatalogs,
	getBookPageContent,
};
